package com.hznu.coursemanagerbackend.shiro;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.hznu.coursemanagerbackend.modules.sys.entity.User;
import com.hznu.coursemanagerbackend.modules.sys.service.UserService;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

/**
 * 1、身份认证
 * 2、权限注入
 */
@Component
public class AuthRealm extends AuthorizingRealm {

    private Logger log = LogManager.getLogger(getClass());

    @Autowired
    @Lazy //延时加载（懒加载）
    private UserService userService;

    public AuthRealm(){}
    public AuthRealm(CacheManager cacheManager, CredentialsMatcher matcher) {
        super(cacheManager, matcher);
    }

    /**
     * 登录认证（身份验证）
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {

        log.info("......登录认证......");

        String username = (String)authenticationToken.getPrincipal();
        User user ;

        // 在此也可处理手机号登录

        user = userService.selectOne(new EntityWrapper<User>().eq("username",username));

        if(user == null) {

            throw new UnknownAccountException();//没找到帐号
        }
        log.info(user.getPassword());
        //交给AuthenticatingRealm使用CredentialsMatcher进行密码匹配
        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
                user.getUsername(), //用户名
                user.getPassword(), //密码,不用加密直接传入
                ByteSource.Util.bytes(user.getSalt()),
                getName()  //realm name
        );


        return authenticationInfo;
    }

    /**
     * 权限信息.(授权):
     * 权限注入,  可从DB中查询用户权限进行注入
     * @param principals
     * @return
     *
     * 注：只有在需要权限确认时，才会调用此方法；
     * 如：@RequiresRoles(value="admin")
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {

        log.info("......权限认证......");

        /**
         * 权限注入：可在此注入角色或权限
         */

        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();

//        String username = (String)principals.getPrimaryPrincipal();

        //TODO add roles
//        HashSet<String> rolesSet=new HashSet<String>();
//        rolesSet.add("admin");
//        authorizationInfo.setRoles(rolesSet); //注入角色权限

        //TODO add permits
//            HashSet<String> permissionsSet=new HashSet<String>();
//            permissionsSet.add("user:update");
//            authorizationInfo.setStringPermissions(permissionsSet); //注入权限串

        return authorizationInfo;
    }

}
